/**
 * 手写 Promise
 */

 const SUCCESS = 'fulfilled'
 const FAILURE = 'rejected'
 const PENDING = 'pending'
 
 //1.基本结构
 function myPromise(executor) {
   let self = this;
   self.status = PENDING; //状态
   self.value = undefined; //成功结果
   self.reason = undefined; //失败原因
 
   // 7.解决异步问题 => 暂存区
   self.onFulfilledCallbacks = [];//成功的回调
   self.onRejectedCallbacks = []; //失败的回调
 
 
   //返回成功的结果
   resolve = value => {
     //5.1
     if (self.status === PENDING) {
       self.value = value; //保存成功结果
       self.status = SUCCESS;
       //8.存储起来后，当resolve或者reject异步执行的时候就可以来调用了
       self.onFulfilledCallbacks.forEach(fn => fn(value))
     }
   }
 
   //返回失败的结果
   reject = reason => {
     //5.2
     if (self.status === PENDING) {
       self.reason = reason; //保存失败结果
       self.status = FAILURE;
       //9.状态改变时执行存起来的失败回调
       self.onRejectedCallbacks.forEach(fn => fn(reason))
     }
   }
   //4. executor => 文件执行
   try {
     executor(resolve, reject);//手动地 resolve 和 reject 一个 Promise
   } catch (err) {
     reject(err);
   }
 }
 
 //2.每一个promise都有一个then() new继承
 myPromise.prototype.then = function (onFulfilled, onRejected) {
   
   //6. 返回一个新的promise，解决潜逃回调then
   onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (data) { resolve(data) };
   onRejected = typeof onRejected === 'function' ? onRejected : function (err) { throw err };
   //7.
   let self = this;
   // 添加订阅器
   // if (self.status === PENDING) {
   // 	self.onFulfilledCallbacks.push(onFulfilled)
   // 	self.onRejectedCallbacks.push(onRejected)
   // }
   
   return new myPromise((resolve, reject) => {
     if (self.status === SUCCESS) {
       try {
         let val = onFulfilled(self.value);
         // then里面也要return一个promise
         resolvePromise(val,resolve,reject);
       } catch (err) {
         reject(err)
       }
     }
 
     if (self.status === FAILURE) {
       try {
         let val = onRejected(self.reason);
         resolvePromise(val,resolve,reject);
       } catch (err) {
         reject(err)
       }
     }
 
     if (self.status === PENDING) {
       self.onFulfilledCallbacks.push(() => {
         let val = onFulfilled(self.value);
         resolvePromise(val,resolve,reject);
       })
       self.onRejectedCallbacks.push(() => {
         let val = onRejected(self.reason);
         resolvePromise(val,resolve,reject);
       })
     }
   })
 }
 
 myPromise.prototype.catch = function (fn) {
   return this.then(null, fn)
 }
 
 function resolvePromise(value,resolve,reject){
   value instanceof myPromise ? value.then(resolve, reject) : resolve(value);
 }
 
 module.exports = myPromise;   